package com.liuzy.crawler.core;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

/**
 * @author liuzy
 * @since 2015年9月22日
 */
public class FileScan {
	public static void main(String[] args) throws Exception {
		File file = new File("D:\\_DownLoad\\_cache\\www.taobao.com");
		FileScan fileScan = new FileScan(file);
		for (String url : fileScan.scanAll()) {
			System.out.println(url);
		}
		System.out.println("耗时:" + fileScan.getUseTime() + "ms");
	}
	private File file;
	private String fileName;
	private String siteName;
	private boolean cache;
	private boolean image;
	private ArrayList<String> cacheList = new ArrayList<>();
	private ArrayList<String> imageList = new ArrayList<>();
	private volatile boolean isRun = true;
	private int status;
	private char[] buffer = new char[]{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '};
	private long useTime = System.currentTimeMillis();

	public FileScan(String filePath) {
		this.file = new File(filePath);
		this.fileName = file.getName();
		if (fileName.contains("_")) {
			siteName = fileName.substring(0, fileName.indexOf("_"));
		} else {
			siteName = fileName;
		}
	}

	public FileScan(File file) {
		this.file = file;
		this.fileName = file.getName();
		if (fileName.contains("_")) {
			siteName = fileName.substring(0, fileName.indexOf("_"));
		} else {
			siteName = fileName;
		}
	}

	public List<String> scanCache() throws Exception {
		cache = true;
		scaning();
		return this.cacheList;
	}

	public List<String> scanImage() throws Exception {
		image = true;
		scaning();
		return this.imageList;
	}

	public List<String> scanAll() throws Exception {
		cache = true;
		image = true;
		scaning();
		List<String> all = new ArrayList<>();
		all.addAll(this.cacheList);
		all.addAll(this.imageList);
		return all;
	}

	public int scan() {
		cache = true;
		image = true;
		try {
			if (!file.exists()) {
				return 1;
			}
			scaning();
			return 0;
		} catch (Exception e) {
			System.out.println(fileName + "|" + e.getMessage());
			return 4;
		}
	}

	private void scaning() throws Exception {
		Reader reader = new InputStreamReader(new FileInputStream(file));
		int temp;
		StringBuffer sb = new StringBuffer(" ");
		while (isRun && (temp = reader.read()) != -1) {
			char ch = (char) temp;
//			System.out.print("|"+ch);
			switch (status) {
			case 0:
				status = toBuffer(ch);
				break;
			case 1:// http://
				if (isPairs(buffer[0], ch)) {
					status = 0;
					String url = sb.toString();
					if (url.length() > 0) {
						forward(url);
						sb.setLength(0);
					}
				} else
					sb.append(ch);
				break;
			case 2:// src="/ href="/
			case 3:// src='/ href='/
			case 4:// src=/ href=/
				if (isPairs(buffer[0], ch)) {
					status = 0;
					String url = sb.toString();
					if (url.length() > 0) {
						forward(siteName + "/" + url);
						sb.setLength(0);
					}
				} else
					sb.append(ch);
				break;
			default:
				break;
			}
		}
		reader.close();
		this.useTime = System.currentTimeMillis() - useTime;
	}

	/** 把当前字符添加到buffer并验证 */
	private int toBuffer(char ch) {
		buffer[0] = buffer[1];
		buffer[1] = buffer[2];
		buffer[2] = buffer[3];
		buffer[3] = buffer[4];
		buffer[4] = buffer[5];
		buffer[5] = buffer[6];
		buffer[6] = buffer[7];
		buffer[7] = ch;
		String temp = new String(buffer).substring(1);
		if (temp.startsWith("src=/") || temp.startsWith("href=/")) {
			buffer[0] = ' ';
			return 4;
		} else if (temp.startsWith("src=\'/") || temp.startsWith("href=\'/")) {
			buffer[0] = '\'';
			return 3;
		} else if (temp.startsWith("src=\"/") || temp.startsWith("href=\"/")) {
			buffer[0] = '"';
			return 2;
		} else if (temp.startsWith("http://")) {
			return 1;
		} else {
			return 0;
		}
	}

	/** 判断buffer[0]和当前字符ch是不是一对 */
	private boolean isPairs(char left, char right) {
		switch (left) {
		case ' ':
			return right == ' ' || right == '\r' || right == '\t' || right == '\n';
		case '=':
			return right == '\'' || right == '\"';
		case '\'':
			return right == '\'';
		case '\"':
			return right == '\"';
		case '(':
			return right == ')';
		default:
			return false;
		}
	}

	private void forward(String url) {
		char lastChar = url.charAt(url.length() - 1);
		if (lastChar == '\\' || lastChar == '/') {
			url = url.substring(0, url.length() - 1);
		}
//		System.out.println(new String(buffer) + "|" + url);
		// 第一道：直接过滤掉
		if (url.equals("www")
				|| url.contains(".js?")
				|| url.contains(".css?")
				|| url.contains("+")
				|| url.contains("(")
				|| url.contains(")")
				|| url.contains("<")
				|| url.contains(">")
				|| url.contains("${")
				|| url.contains("javascript")
				|| url.contains("www.w3.org")) {
//			System.out.println(new String(buffer) + "|" + url);
			return;
		}
		// 第二道：再处理
		if (url.contains(".gif?")
				|| url.contains(".jpeg?")
				|| url.contains(".jpg?")
				|| url.contains(".png?")) {
			url = url.substring(0, url.indexOf("?"));
		}
		// 第三道：直接过滤掉
		String suffix = "";
		if (url.contains("."))
			suffix = url.substring(url.lastIndexOf(".")).toLowerCase();
		if (suffix.startsWith(".dtd")
				|| suffix.startsWith(".js")
				|| suffix.startsWith(".ico")
				|| suffix.startsWith(".css")
				|| suffix.startsWith(".exe")
				|| suffix.startsWith(".xml")) {
			return;
		}
		switch (suffix) {
		case ".gif":
		case ".jpeg":
		case ".jpg":
		case ".png":
			if (image)
				imageList.add(url);
			break;
		default:
//			System.out.println(new String(buffer) + "|" + url);
			if (cache)
				cacheList.add(url);
			break;
		}
	}

	public ArrayList<String> getCacheList() {
		return cacheList;
	}

	public ArrayList<String> getImageList() {
		return imageList;
	}

	public String getFileName() {
		return fileName;
	}

	public long getUseTime() {
		return useTime;
	}

}
